package hystrix;

import com.netflix.config.ConfigurationManager;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import org.apache.commons.lang.StringUtils;
import rest.entity.User;
import rx.Observable;
import rx.Observer;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

public class HelloCommandMain {

    static String  url = "http://localhost:9100/";
    public static void main(String[] args) throws InterruptedException, ExecutionException {
//        simpleHystrix();
        HelloCommandMain helloCommandMain = new HelloCommandMain();
//        helloCommandMain.testCommand();
//        helloCommandMain.testSubCommand();
//        helloCommandMain.testTimeoutBreaker();
        helloCommandMain.testCollapser();
    }



    private static void simpleHystrix() {
        String fullUrl = url + "hello";
        HelloCommand helloCommand = new HelloCommand(fullUrl,"简单测试helloCommand");
        String execute = helloCommand.execute();
        System.out.println("执行结果：" + execute);

        //HelloCommand不能多次启动
//        String execute1 = helloCommand.execute();
//        System.out.println("再次执行hello执行结果：" + execute1);
        fullUrl = url + "errHello";
        HelloCommand errorhelloCommand = new HelloCommand(fullUrl,"简单测试errorCommand");
        String execute2 = errorhelloCommand.execute();
        System.out.println("执行结果：" + execute2);
    }

    /**
     * 测试4种执行方式，需要启动springboot
     * @throws InterruptedException
     */
    void testCommand() throws InterruptedException {
        String fullUrl = url + "hello";
        HelloCommand command;
        System.out.println("--------execute--------------");
        command = new HelloCommand(fullUrl, "execute方法");
        command.execute();
        System.out.println("---------execute 结束--------------------------");
        System.out.println("--------queue--------------");
        command = new HelloCommand(fullUrl, "queue方法");
        command.queue();
        System.out.println("---------queue 结束--------------------------");
        System.out.println("--------observe--------------");
        command = new HelloCommand(fullUrl, "observe方法");
        command.observe();
        System.out.println("--------observe 结束---------------------------");
        System.out.println("--------toObsevable--------------");
        command = new HelloCommand(fullUrl, "toObservable方法");
        Observable<String> toObservable = command.toObservable();
        System.out.println("--------toObsevable 结束---------------------------");
        Thread.sleep(3000);
        System.out.println("--------toObsevable 线程睡完了---------------------------");
        toObservable.subscribe(new Observer<String>() {
            public void onCompleted() {
                System.out.println("命令执行完成");
            }

            public void onError(Throwable throwable) {
                System.out.println("出现异常了");
            }

            public void onNext(String s) {
                System.out.println("执行结果:" + s);
            }
        });
    }

    /**
     * 测试回滚链，不需要启动springboot
     */
    void testSubCommand(){
        String fullUrl = url + "hello";
        HelloCommand command = new HelloCommand(fullUrl,"测试fall back的关联调用");
        command.execute();
    }

    /**
     * 测试断路机制
     *
     */
    void testTimeoutBreaker(){
        int timeout = 1000;
        //设置超时时间
//        ConfigurationManager.getConfigInstance().setProperty("hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds",timeout);
        //设置断路器阀值的统计周期时长
        ConfigurationManager.getConfigInstance().setProperty("hystrix.command.default.metrics.rollingStats.timeInMilliseconds",20000);
        //设置断路器阀值，在一个统计周期时长中，触发阀值的访问次数
        ConfigurationManager.getConfigInstance().setProperty("hystrix.command.default.circuitBreaker.requestVolumeThreshold",5);
        //触发断路的错误百分比
        ConfigurationManager.getConfigInstance().setProperty("hystrix.command.default.circuitBreaker.errorThresholdPercentage",20);
        String fullUrl = url + "hello?time=" + timeout;
        for(int i = 0 ;i<15;i++){
            SubCommand subCommand = new SubCommand("subcommand",fullUrl);
            System.out.println("第" + i +"次调用前，断路器的情况：" + subCommand.isCircuitBreakerOpen());
            String execute = subCommand.execute();
            if(StringUtils.isNotBlank(execute)){
                System.out.println("成功从服务器端接收结果：" + execute);
            }
            System.out.println("第" + i +"次调用前，断路器的情况：" + subCommand.isCircuitBreakerOpen() + "\n***********************\n");
        }
    }


    void testCollapser() throws ExecutionException, InterruptedException {
        //配置合并命令的等待时间，默认是10毫秒
        ConfigurationManager.getConfigInstance().setProperty("hystrix.command.default.timerDelayInMilliseconds",1000);
        //请求上下文
        HystrixRequestContext hystrixRequestContext = HystrixRequestContext.initializeContext();
        //创建请求
        SingleUserCommand command1 = new SingleUserCommand("123");
        SingleUserCommand command2 = new SingleUserCommand("cccc");
        SingleUserCommand command3 = new SingleUserCommand("dddd");
        SingleUserCommand command4 = new SingleUserCommand("aaaa");
        SingleUserCommand command5 = new SingleUserCommand("bbbb");
        Future<User> user1 = command1.queue();
        Future<User> user2 = command2.queue();
        Future<User> user3= command3.queue();
        Future<User> user4 = command4.queue();
        Future<User> user5 = command5.queue();
        System.out.println("user name: " + user1.get().getUserName() + " ,user id: " + user1.get().getUserId());
        System.out.println("user name: " + user2.get().getUserName() + " ,user id: " + user2.get().getUserId());
        System.out.println("user name: " + user3.get().getUserName() + " ,user id: " + user3.get().getUserId());
        System.out.println("user name: " + user4.get().getUserName() + " ,user id: " + user4.get().getUserId());
        System.out.println("user name: " + user5.get().getUserName() + " ,user id: " + user5.get().getUserId());
        hystrixRequestContext.shutdown();


    }


}
